package com.sxbbc.common.core.wx;

import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.alibaba.fastjson.JSONObject;
import com.sxbbc.common.basics.enums.RandNumType;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.service.config.Config;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.basics.utils.date.DateUtil;
import com.sxbbc.common.basics.utils.radoms.RandNumUtils;
import com.sxbbc.common.basics.wx.WxrequestUrls;
import com.sxbbc.common.basics.wx.util.HttpUtil;
import com.sxbbc.common.basics.wx.util.TenpayUtil;
import com.sxbbc.common.basics.wx.util.WeixinUtil;
import com.sxbbc.common.core.entity.jz.InfoWx;
import com.sxbbc.common.core.utils.RedisUtils;

/**
 * 微信支付签名公用层
 *
 * @author Arno
 */
public class WxPayUtils {

    private static Logger logger = LogManager.getLogger(WxPayUtils.class);

    public static WxPayUtils wxPayUtils = null;
    private static InfoWx infoWx = null;

    public static WxPayUtils getInstance() {
        if (wxPayUtils == null) {
            synchronized (WxPayUtils.class) {
                if (wxPayUtils == null) {
                    wxPayUtils = new WxPayUtils();
                }
            }
        }
        infoWx = RedisUtils.getInstance().getWxInfo();
        return wxPayUtils;
    }

    /**
     * 微信web 二维码 签名
     *
     * @param payCode    交易单号
     * @param orderPrice 订单金额
     * @param NoticeURL  回调地址
     * @return 返回支付url
     */
    public String getPayParaQrWeb(String payCode, String orderPrice, String NoticeURL) {
        String url = null;
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // appid
            paramMap.put("appid", infoWx.getAppId());
            // 描述
            paramMap.put("body", infoWx.getBody());
            // 商户号
            paramMap.put("mch_id", infoWx.getMchId());
            // 随机数a
            paramMap.put("nonce_str", noncestr);
            // 支付成功后，回调地址
            paramMap.put("notify_url", NoticeURL);
            // 商户 后台的贸易单号
            paramMap.put("out_trade_no", payCode);
            // 商户根据自己业务传递的参数 必填
            paramMap.put("product_id", payCode);
            // 本机的Ip
            paramMap.put("spbill_create_ip", "");
            // 金额必须为整数 单位为分
            paramMap.put("total_fee", orderPrice);
            // 交易类型
            paramMap.put("trade_type", "NATIVE");
            // 根据微信签名规则，生成签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信二维码支付第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String resdata = WeixinUtil.Unifiedorder(xmlData);
            logger.info("微信二维码支付二次验签" + resdata);
            Document dd = DocumentHelper.parseText(resdata);
            if (dd != null) {
                Element root = dd.getRootElement();
                if (root == null) {
                    return "";
                }
                Element returnCode = root.element("return_code");
                String code = returnCode.getText();
                if (StringUtils.isBlank(code) || !"SUCCESS".equals(code.toUpperCase())) {
                    throw new ThrowJsonException("签名失败");
                }
                Element codeUrl = root.element("code_url");
                // 解析 xml 获得 code_url
                url = codeUrl.getText();
            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return url;
    }

    /**
     * 微信手机端支付
     *
     * @param payCode
     * @param orderPrice
     * @param NoticeURL
     * @return
     */
    public String getPayParaQrMobile(HttpServletRequest request, String payCode, String orderPrice,
                                     String NoticeURL) {
        String url = null;
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // appid
            paramMap.put("appid", infoWx.getAppId());
            // 描述
            paramMap.put("body", infoWx.getBody());
            // 商户号
            paramMap.put("mch_id", infoWx.getMchId());
            // 随机数
            paramMap.put("nonce_str", noncestr);
            // 支付成功后，回调地址
            paramMap.put("notify_url", NoticeURL);
            // 商户 后台的贸易单号
            paramMap.put("out_trade_no", payCode);
            // 商户根据自己业务传递的参数 必填
            paramMap.put("product_id", payCode);
            // 本机的Ip
            paramMap.put("spbill_create_ip", CalcuUtils.getInstance().getRemoteHost(request));
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type", "Wap");
            jsonObject.put("wap_url", Config.properties.getWapDomain());
            jsonObject.put("wap_name", infoWx.getWxName());
            JSONObject object = new JSONObject();
            object.put("h5_info", jsonObject);
            paramMap.put("scene_info", object.toJSONString());
            // 金额必须为整数 单位为分
            paramMap.put("total_fee", orderPrice);
            // 交易类型
            paramMap.put("trade_type", "MWEB");
            // 根据微信签名规则，生成签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信H5支付第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String resdata = WeixinUtil.Unifiedorder(xmlData);
            logger.info("微信H5支付二次验签" + resdata);
            Document dd = DocumentHelper.parseText(resdata);
            if (dd != null) {
                Element root = dd.getRootElement();
                if (root == null) {
                    return "";
                }
                Element returnCode = root.element("return_code");
                String code = returnCode.getText();
                if (StringUtils.isBlank(code) || !"SUCCESS".equals(code.toUpperCase())) {
                    throw new ThrowJsonException("签名失败");
                }
                Element codeUrl = root.element("mweb_url");
                // 解析 xml 获得 code_url
                url = codeUrl.getText();
            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return url;
    }

    /**
     * 公众号支付
     *
     * @param openId     微信用户id
     * @param payCode    交易单号
     * @param orderPrice 支付金额
     * @param NoticeURL  回调地址
     * @return
     */
    public SortedMap<Object, Object> getPayParaPublicAccounts(String openId, String payCode, String orderPrice,
                                                              String NoticeURL) {
        SortedMap<Object, Object> twiceMap = new TreeMap<Object, Object>();
        SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
        String noncestr = TenpayUtil.CreateNoncestr();
        paramMap.put("appid", infoWx.getAppId());
        paramMap.put("body", infoWx.getBody());
        paramMap.put("mch_id", infoWx.getMchId());
        paramMap.put("nonce_str", noncestr);
        paramMap.put("notify_url", NoticeURL);
        paramMap.put("openid", openId);
        paramMap.put("out_trade_no", payCode);
        paramMap.put("total_fee", orderPrice);
        paramMap.put("trade_type", "JSAPI");
        String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
        logger.info("微信公众号第一步签名sign" + sign);
        String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
        logger.info("微信公众号二次签名sign" + sign);
        String resdata = WeixinUtil.Unifiedorder(xmlData);
        Document dd = null;
        try {
            dd = DocumentHelper.parseText(resdata);
            String prepayid = "";
            if (dd != null) {
                Element root = dd.getRootElement();
                Element prePayId = root.element("prepay_id");
                StringUtils.isEmpty(prePayId.getText());
                prepayid = prePayId.getText();
                Element nonceStr = root.element("nonce_str");
                int time = (int) (System.currentTimeMillis() / 1000L);
                twiceMap.put("appId", infoWx.getAppId());
                twiceMap.put("nonceStr", nonceStr.getText());
                twiceMap.put("signType", "MD5");
                twiceMap.put("package", "prepay_id=" + prepayid);
                twiceMap.put("timeStamp", String.valueOf(time));
                String twiceSign = TenpayUtil.createSign("UTF-8", twiceMap, infoWx.getKeyval());
                twiceMap.put("paySign", twiceSign);
            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return twiceMap;
    }

    /**
     * 小程序支付
     *
     * @param openId     微信用户id
     * @param payCode    交易单号
     * @param orderPrice 支付金额
     * @param NoticeURL  回调地址
     * @return
     */
    public SortedMap<Object, Object> getPayParaProgram(String openId, String payCode, String orderPrice,
                                                       String NoticeURL) {
        SortedMap<Object, Object> twiceMap = new TreeMap<Object, Object>();
        SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
        String noncestr = TenpayUtil.CreateNoncestr();
        paramMap.put("appid", infoWx.getProgramAppid());
        paramMap.put("body", infoWx.getBody());
        paramMap.put("mch_id", infoWx.getMchId());
        paramMap.put("nonce_str", noncestr);
        paramMap.put("notify_url", NoticeURL);
        paramMap.put("openid", openId);
        paramMap.put("out_trade_no", payCode);
        paramMap.put("total_fee", orderPrice);
        paramMap.put("trade_type", "JSAPI");
        String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
        logger.info("微信小程序第一步签名sign" + sign);
        String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
        logger.info("微信小程序二次签名sign" + sign);
        String resdata = WeixinUtil.Unifiedorder(xmlData);
        Document dd = null;
        try {
            dd = DocumentHelper.parseText(resdata);
            String prepayid = "";
            if (dd != null) {
                Element root = dd.getRootElement();
                Element prePayId = root.element("prepay_id");
                StringUtils.isEmpty(prePayId.getText());
                prepayid = prePayId.getText();
                Element nonceStr = root.element("nonce_str");
                int time = (int) (System.currentTimeMillis() / 1000L);
                twiceMap.put("appId", infoWx.getProgramAppid());
                twiceMap.put("nonceStr", nonceStr.getText());
                twiceMap.put("signType", "MD5");
                twiceMap.put("package", "prepay_id=" + prepayid);
                twiceMap.put("timeStamp", String.valueOf(time));
                String twiceSign = TenpayUtil.createSign("UTF-8", twiceMap, infoWx.getKeyval());
                twiceMap.put("paySign", twiceSign);
            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return twiceMap;
    }

    /**
     * 微信APP支付
     *
     * @param payCode    交易单号
     * @param orderPrice 金额
     * @param NoticeURL  异步回调地址
     * @return
     */
    public SortedMap<Object, Object> getPayParaWxApp(String payCode, String orderPrice, String NoticeURL) {
        SortedMap<Object, Object> twiceMap = new TreeMap<Object, Object>();
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // appid
            paramMap.put("appid", infoWx.getMappId());
            // 描述
            paramMap.put("body", infoWx.getBody());
            // 商户号
            paramMap.put("mch_id", infoWx.getAppMchId());
            // 随机数
            paramMap.put("nonce_str", noncestr);
            // 支付成功后，回调地址
            paramMap.put("notify_url", NoticeURL);
            // 商户 后台的贸易单号
            paramMap.put("out_trade_no", payCode);
            // 金额必须为整数 单位为分
            paramMap.put("total_fee", orderPrice);
            // 交易类型
            paramMap.put("trade_type", "APP");
            // 根据微信签名规则，生成签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getAppKeyval());
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String resdata = WeixinUtil.Unifiedorder(xmlData);
            logger.info("微信APP支付签名结果" + resdata);
            // 第一次签名成功 则做第二次签名
            Document dd = null;
            try {
                dd = DocumentHelper.parseText(resdata);
            } catch (DocumentException e) {
                return null;
            }
            if (dd != null) {
                Element root = dd.getRootElement();
                if (root == null) {
                    return null;
                }
                Element prePayId = root.element("prepay_id");
                if (StringUtils.isEmpty(prePayId.getText())) {
                    return null;
                }
                Element nonceStr = root.element("nonce_str");
                int time = (int) (System.currentTimeMillis() / 1000);
                twiceMap.put("appid", infoWx.getMappId());
                twiceMap.put("noncestr", nonceStr.getText());
                twiceMap.put("package", "Sign=WXPay");
                twiceMap.put("partnerid", infoWx.getAppMchId());
                twiceMap.put("prepayid", prePayId.getText());
                twiceMap.put("timestamp", time);
                String twiceSign = TenpayUtil.createSign("UTF-8", twiceMap, infoWx.getAppKeyval());
                twiceMap.put("sign", twiceSign);
            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return twiceMap;
    }

    /**
     * 查询微信订单
     *
     * @param payCode 根据交易单号查询
     * @return
     */
    public Map<String, String> queryWxOrder(String payCode) {
        Map<String, String> map = new HashMap<String, String>();
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // appid
            paramMap.put("appid", infoWx.getAppId());
            // 商户号
            paramMap.put("mch_id", infoWx.getMchId());
            // 随机数
            paramMap.put("nonce_str", noncestr);
            // 商户 后台的贸易单号
            paramMap.put("out_trade_no", payCode);
            // 根据微信签名规则，生成签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String resdata = WeixinUtil.Unifiedorder_query(xmlData);
            logger.info("查询微信订单二次验签" + resdata);
            Document dd = null;
            try {
                dd = DocumentHelper.parseText(resdata);
                if (dd != null) {
                    Element root = dd.getRootElement();
                    if (root != null) {
                        Element resultCode = root.element("result_code");
                        if (resultCode != null) {
                            map.put("result_code", resultCode.getText());
                        }
                        Element openId = root.element("openid");
                        if (openId != null) {
                            map.put("openid", openId.getText());
                        }
                        Element tradeState = root.element("trade_state");
                        if (tradeState != null) {
                            map.put("trade_state", tradeState.getText());
                        }
                        Element transactionId = root.element("transaction_id");
                        if (transactionId != null) {
                            map.put("transaction_id", transactionId.getText());
                        }
                        Element totalFee = root.element("total_fee");
                        if (totalFee != null) {
                            map.put("total_fee", totalFee.getText());
                        }
                    }
                }
            } catch (Exception e) {
                throw new ThrowJsonException("对账失败");
            }

        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        return map;
    }

    /**
     * 微信扫码收银
     *
     * @param payCode    交易单号
     * @param authCode   对方付款条码
     * @param orderPrice 订单金额
     * @return 返回支付结果
     */
    public Map<String, String> getPayParaScanCash(String payCode, String authCode, String orderPrice) {
        Map<String, String> map = new HashMap<String, String>();
        String code = "fail";
        String transCode = "";
        String openId = "";
        String msg = "";
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // appid
            paramMap.put("appid", infoWx.getAppId());
            // 收银对方付款条码
            paramMap.put("auth_code", authCode);
            // 描述
            paramMap.put("body", infoWx.getBody());
            // 商户号
            paramMap.put("mch_id", infoWx.getMchId());
            // 随机数
            paramMap.put("nonce_str", noncestr);
            // 商户 后台的贸易单号
            paramMap.put("out_trade_no", payCode);
            // 金额必须为整数 单位为分
            paramMap.put("total_fee", orderPrice);
            // 根据微信签名规则，生成签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信收银刷卡第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String resdata = WeixinUtil.Unifiedorder_shouying(xmlData);
            logger.info("微信收银刷卡支付二次验签" + resdata);
            Document dd = DocumentHelper.parseText(resdata);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                if (resultCode != null) {
                    code = resultCode.getText();
                }
                Element transactionId = root.element("transaction_id");
                if (transactionId != null) {
                    transCode = transactionId.getText();
                }
                Element openIdText = root.element("openid");
                if (openIdText != null) {
                    openId = openIdText.getText();
                }
                Element errCodeDes = root.element("err_code_des");
                if (errCodeDes != null) {
                    msg = errCodeDes.getText();
                }

            }
        } catch (Exception e) {
            throw new ThrowJsonException("签名失败");
        }
        map.put("code", code);
        map.put("transcode", transCode);
        map.put("openid", openId);
        map.put("msg", msg);
        logger.info("微信收银刷卡支付最后结果MAP" + map);
        return map;
    }

    /**
     * 微信退款
     *
     * @param transCode 微信支付商户产生的订单号
     * @param totalFee  订单实际支付总金额
     * @param refundFee 退款金额
     * @return
     * @paran refundCode 退款编号
     */
    public String getPayParaRefund(String transCode, String refundCode, String totalFee,
                                   String refundFee) {
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            paramMap.put("appid", infoWx.getAppId());
            paramMap.put("mch_id", infoWx.getMchId());
            paramMap.put("nonce_str", noncestr);
            paramMap.put("transaction_id", transCode);
            paramMap.put("out_refund_no", refundCode);
            paramMap.put("total_fee", totalFee);
            paramMap.put("refund_account", "REFUND_SOURCE_RECHARGE_FUNDS");
            paramMap.put("refund_fee", refundFee);
            paramMap.put("op_user_id", infoWx.getMchId());
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信退款第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String refund = HttpUtil.postCert(infoWx.getCerturl(), infoWx.getMchId(), xmlData,
                    WxrequestUrls.WX_REFUND_URL);
            logger.info("微信退款结果xml" + refund);
            Document dd = DocumentHelper.parseText(refund);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                Element errCodeDes = root.element("err_code_des");
                if (resultCode != null) {
                    String code = resultCode.getText();
                    if ("SUCCESS".equals(code.toUpperCase())) {
                        return "";
                    } else {
                        return errCodeDes.getText();
                    }
                } else {
                    return errCodeDes.getText();
                }
            }
        } catch (Exception e) {
            logger.info("编号：【" + refundCode + "】微信退款失败," + e.getMessage());
            return "退款异常";
        }
        return "退款失败";
    }

    /**
     * app微信退款
     *
     * @param transCode  微信支付商户产生的订单号
     * @param refundCode 退款编号
     * @param totalFee   订单实际支付金额
     * @param refundFee  退款金额
     * @return
     * @author xiaoky
     */
    public String getPayParaRefundApp(String transCode, String refundCode, String totalFee,
                                      String refundFee) {
        String url = infoWx.getAppCerturl();
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            paramMap.put("appid", infoWx.getAppId());
            paramMap.put("mch_id", infoWx.getAppMchId());
            paramMap.put("nonce_str", noncestr);
            paramMap.put("transaction_id", transCode);
            paramMap.put("out_refund_no", refundCode);
            paramMap.put("total_fee", totalFee);
            paramMap.put("refund_account", "REFUND_SOURCE_RECHARGE_FUNDS");
            paramMap.put("refund_fee", refundFee);
            paramMap.put("op_user_id", infoWx.getAppMchId());
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getAppKeyval());
            logger.info("微信退款第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String refund = HttpUtil.postCert(url, infoWx.getAppMchId(), xmlData,
                    WxrequestUrls.WX_REFUND_URL);
            logger.info("微信退款结果xml" + refund);
            Document dd = DocumentHelper.parseText(refund);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                Element errCodeDes = root.element("err_code_des");
                if (resultCode != null) {
                    String code = resultCode.getText();
                    if ("SUCCESS".equals(code.toUpperCase())) {
                        return "";
                    } else {
                        return errCodeDes.getText();
                    }
                } else {
                    return errCodeDes.getText();
                }
            }
        } catch (Exception e) {
            logger.info("编号：【" + refundCode + "】微信退款失败," + e.getMessage());
            return "退款异常";
        }
        return "退款失败";
    }

    /**
     * 微信提现到红包
     *
     * @param request
     * @param openId     提现用户openid
     * @param totalMoney 提现金额
     * @param num        红包数量
     * @return
     */
    public boolean getPayParaRedPack(HttpServletRequest request, String openId, String totalMoney,
                                     String num) {
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            String mchBillNo = infoWx.getMchId() + DateUtil.getInstance().toDateString(DateUtil.getInstance().currentDate(), "yyyymmdd")
                    + RandNumUtils.getInstance().get(RandNumType.NUMBER, 10);
            // 活动名称
            paramMap.put("act_name", "Cash");
            // 调用接口的机器Ip地址
            paramMap.put("client_ip", CalcuUtils.getInstance().getRemoteHost(request));
            paramMap.put("mch_billno", mchBillNo);
            // 微信支付分配的商户号
            paramMap.put("mch_id", infoWx.getMchId());
            paramMap.put("nonce_str", noncestr);
            // 备注信息
            paramMap.put("remark", "Thanks");
            // "oy-yfuAMQ4tynMP98bOdMmuS4Bk4"; // 接受红包的用户.用户在wxappid下的openid
            paramMap.put("re_openid", openId);
            // 商户名称, 红包发送者名称
            paramMap.put("send_name", "Cash");
            // 付款金额，单位分
            paramMap.put("total_amount", totalMoney);
            // 红包发放总人数
            paramMap.put("total_num", num);
            // 红包祝福语
            paramMap.put("wishing", "Cash");
            // 微信分配的公众账号ID（企业号corpid即为此appId）
            paramMap.put("wxappid", infoWx.getAppId());

            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信红包第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml(paramMap, sign);
            String refund = HttpUtil.postCert(infoWx.getCerturl(), infoWx.getMchId(), xmlData,
                    WxrequestUrls.WX_REDPACK_URL);
            logger.info("微信红包结果xml" + refund);
            Document dd = DocumentHelper.parseText(refund);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                if (resultCode != null) {
                    String code = resultCode.getText();
                    if ("SUCCESS".equals(code.toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        } catch (Exception e) {
            throw new ThrowJsonException("失败");
        }
        return false;
    }

    /**
     * 微信转账到零钱
     *
     * @param request
     * @param openId
     * @param totalMoney
     * @param payCode
     * @return
     */
    public boolean getPayParaTrans(HttpServletRequest request, String openId, String totalMoney,
                                   String payCode) {
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
            String noncestr = TenpayUtil.CreateNoncestr();
            // 付款金额，单位分
            paramMap.put("amount", totalMoney);
            paramMap.put("check_name", "NO_CHECK");
            paramMap.put("desc", "DDCAT");
            // 微信分配的公众账号ID（企业号corpid即为此appId）
            paramMap.put("mch_appid", infoWx.getAppId());
            // 微信支付分配的商户号
            paramMap.put("mchid", infoWx.getMchId());
            paramMap.put("nonce_str", noncestr);
            // "oy-yfuAMQ4tynMP98bOdMmuS4Bk4";
            paramMap.put("openid", openId);
            paramMap.put("partner_trade_no", payCode);
            // 调用接口的机器Ip地址
            paramMap.put("spbill_create_ip", CalcuUtils.getInstance().getRemoteHost(request));
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信转账第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml_twice(paramMap, sign);
            String refund = HttpUtil.postCert(infoWx.getCerturl(), infoWx.getMchId(), xmlData,
                    WxrequestUrls.WX_TRANS_URL);
            logger.info("微信转账结果xml" + refund);
            Document dd = DocumentHelper.parseText(refund);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                if (resultCode != null) {
                    String code = resultCode.getText();
                    if ("SUCCESS".equals(code.toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        } catch (Exception e) {
            throw new ThrowJsonException("转账失败");
        }
        return false;
    }


    /**
     * 微信转账到银行卡
     *
     * @param request
     * @param bankCardNo 银行卡号
     * @param totalMoney
     * @param payCode
     * @return
     */
    public boolean getPayParaTransToBankcard(String bankcode, String bankCardNo, String bankHolderName,
                                             String totalMoney, String payCode) {
        try {
            SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();

            // 微信支付分配的商户号
            paramMap.put("mch_id", infoWx.getMchId());
            //商户企业付款单号
            paramMap.put("partner_trade_no", payCode);
            //随机字符串
            String noncestr = TenpayUtil.CreateNoncestr();
            paramMap.put("nonce_str", noncestr);
            //收款方开户行
            paramMap.put("bank_code", bankcode);

            //RSA工具类提供了，根据加载PKCS8密钥文件的方法
            //PublicKey pub = RSAUtils.getPubKey("C:/Users/Jane/Desktop/pksc8_public.pem", "RSA");
            PublicKey pub = RSAUtils.getPubKey(infoWx.getRsaPublickeyUrl(), "RSA");
            //rsa是微信付款到银行卡要求我们填充的字符串
            String rsa = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
            // 银行卡号进行加密
            byte[] estr = RSAUtils.encrypt(bankCardNo.getBytes(), pub, 2048, 11, rsa);   //对银行账号进行base加密
            // 收款者姓名进行加密
            byte[] holdername = RSAUtils.encrypt(bankHolderName.getBytes(), pub, 2048, 11, rsa);   //对银行账号进行base加密

            //收款方银行卡号,并转为base64格式
            paramMap.put("enc_bank_no", Base64Utils.encode(estr));
            //收款方用户名,并转为base64格式
            paramMap.put("enc_true_name", Base64Utils.encode(holdername));
            // 付款金额，单位分
            paramMap.put("amount", totalMoney);
            paramMap.put("desc", "微信转账到银行卡");
            //签名
            String sign = TenpayUtil.createSign("UTF-8", paramMap, infoWx.getKeyval());
            logger.info("微信转账到银行卡第一步签名sign" + sign);
            String xmlData = TenpayUtil.getRequestXml_twice(paramMap, sign);
            //证书
            //String refund = HttpUtil.postCert("C:/Users/Jane/Desktop/apiclient_cert.p12", infoWx.getMchId(), xmlData, WxrequestUrls.WX_TRANSTOBANKCARD_URL);
            String refund = HttpUtil.postCert(infoWx.getCerturl(), infoWx.getMchId(), xmlData, WxrequestUrls.WX_TRANSTOBANKCARD_URL);
            logger.info("微信转账到银行卡结果xml" + refund);
            Document dd = DocumentHelper.parseText(refund);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("result_code");
                if (resultCode != null) {
                    String code = resultCode.getText();
                    if ("SUCCESS".equals(code.toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        } catch (Exception e) {
            throw new ThrowJsonException("转账到银行卡操作失败");
        }
        return false;
    }


    /**
     * 查询付款到银行卡进度
     * @return
     */
    public String queryTransToBankProcess(String payCode) {
        try {
            SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
            String nonce_str = TenpayUtil.CreateNoncestr();
            parameters.put("mch_id", infoWx.getMchId());
            parameters.put("nonce_str", nonce_str);
            parameters.put("partner_trade_no", payCode);
            String sign = TenpayUtil.createSign("UTF-8", parameters, infoWx.getKeyval());
            String xmlData = TenpayUtil.getRequestXml_twice(parameters, sign);
            String cert = HttpUtil.postCert(infoWx.getCerturl(), infoWx.getMchId(), xmlData, WxrequestUrls.WX_QUERY_TRANSTOBANK);
            Document dd = DocumentHelper.parseText(cert);
            if (dd != null) {
                Element root = dd.getRootElement();
                Element resultCode = root.element("status");
                if (resultCode != null) {
                    String status = resultCode.getText();
                    return status;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


}
